﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using System.Text;

namespace Dycox.Validation
{
    [Serializable]
    public class RequiredValidator : Validator
    {
        protected internal override ValidationResult IsValid(object value, PropertyValidationContext context)
        {
            if (value == null) return ValidationResult.Invalid;

            if (value is string)
            {
                string text = (string)value;
                if (_trimWhiteSpaces) text = text.Trim();
                return (text.Length > 0) ? ValidationResult.Valid : ValidationResult.Invalid;
            }

            if (value == Type.Missing || Convert.IsDBNull(value))
                return ValidationResult.Invalid;
            
            return IsEmpty(value) ? ValidationResult.Invalid : ValidationResult.Valid;
        }

        private bool IsEmpty(object value)
        {
            ICollection coll = value as ICollection;
            if (coll != null) return coll.Count == 0;

            Type type = value.GetType();
            PropertyInfo p = type.GetProperty("IsEmpty", BindingFlags.Public | BindingFlags.Instance);
            if (p != null && p.PropertyType == typeof(bool))
                return (bool)p.GetValue(value, null);

            var members = type.FindMembers(MemberTypes.Field | MemberTypes.Property, BindingFlags.Static | BindingFlags.Public, Type.FilterName, "Empty");
            if (members.Length > 0)
            {
                FieldInfo fld = members[0] as FieldInfo;
                if (fld != null)
                    return object.Equals(value, fld.GetValue(null));

                p = members[0] as PropertyInfo;
                return object.Equals(value, p.GetValue(null, null));
            }

            object value0 = value;
            
            value = "Empty";
            if (Dycox.Utils.ConvertUtil.TryConvertType(ref value, type))
                return object.Equals(value0, value);

            value0 = string.Empty;
            if (Dycox.Utils.ConvertUtil.TryConvertType(ref value, type))
                return object.Equals(value0, value);

            return false;
        }

        private bool _trimWhiteSpaces;
        [DefaultValue(false)]
        public bool TrimWhiteSpaces
        {
            get { return _trimWhiteSpaces; }
            set { _trimWhiteSpaces = value; }
        }

    }

}
